//***************************************************************************************

//利用轮廓信息实现形状匹配-其中canny边缘低阈值为100，高阈值为200，且对轮廓图使用模板匹配方法也是5:归一化系数匹配法

//***************************************************************************************

#include "ImageDecMat.hpp"

void ImageDecMat::on_shapeFeatures(cv::Mat Image1,cv::Mat Image2,cv::Mat& Image3)
{
    int lowThresh=100;
    int highThresh=200;
    int matchMethod=5;
    cv::Mat out_grayImage1,out_grayImage2;
    std::vector<std::vector<cv::Point>>src_contours,tmp_contours,match_contours;
    std::vector<cv::Vec4i>src_hierarchy,tmp_hierarchy;
    //使用canny边缘检测，这里的阈值很关键，可调！
    Canny(Image1, out_grayImage1, lowThresh, highThresh,3);
    Canny(Image2, out_grayImage2, lowThresh, highThresh,3);
    //找到轮廓
    findContours(out_grayImage1, src_contours, src_hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE,cv::Point(0,0));
    findContours(out_grayImage2, tmp_contours, tmp_hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE,cv::Point(0,0));
    //计算矩
    std::vector<CvMoments>src_mu(src_contours.size());
    std::vector<CvMoments>tmp_mu(tmp_contours.size());
    for(unsigned int i=0;i<src_contours.size();++i)
    {
        src_mu[i]=moments(src_contours[i],false);
    }
    for(unsigned int i=0;i<tmp_contours.size();++i)
    {
        tmp_mu[i]=moments(tmp_contours[i],false);
    }
    //计算中心矩
    std::vector<cv::Point2f>src_mc(src_contours.size());
    std::vector<cv::Point2f>tmp_mc(tmp_contours.size());
    for(unsigned int i=0;i<src_contours.size();++i)
    {
        src_mc[i]=cv::Point2f(static_cast<float>(src_mu[i].m10/src_mu[i].m00),static_cast<float>(src_mu[i].m01/src_mu[i].m00));
    }
    for(unsigned int i=0;i<tmp_contours.size();++i)
    {
        tmp_mc[i]=cv::Point2f(static_cast<float>(tmp_mu[i].m10/tmp_mu[i].m00),static_cast<float>(tmp_mu[i].m01/tmp_mu[i].m00));
    }
    //计算Hu矩
    std::vector<CvHuMoments> src_hu(src_contours.size()),tmp_hu(tmp_contours.size());
    for(unsigned int i=0;i<src_contours.size();++i)
    {
        cvGetHuMoments(&src_mu[i], &src_hu[i]);
        std::cout<<"src_Hu:"<<src_hu[i].hu1<<std::endl;
    }
    for(unsigned int i=0;i<tmp_contours.size();++i)
    {
        cvGetHuMoments(&tmp_mu[i], &tmp_hu[i]);
        std::cout<<"tmp_Hu:"<<tmp_hu[i].hu1<<std::endl;
    }
    //利用Hu矩进行匹配
    double matchVal;
    for(unsigned int i=0;i<tmp_contours.size();++i)
    {
        matchVal=cv::matchShapes(src_contours[i],tmp_contours[i], 2, 0.0);
        if(matchVal>0.0)
        {
            match_contours.push_back(tmp_contours[i]);
        }
        std::cout<<"matchVal: "<<matchVal<<std::endl;
    }
    
    
    //***********************绘制轮廓*********************************
    cv::Mat dstImage=cv::Mat::zeros(out_grayImage1.size(), CV_8UC3);
    for(unsigned int i=0;i<src_contours.size();++i)
    {
        //随机生成颜色值
        cv::Scalar color=cv::Scalar(0,0,255);
        //绘制外层和内层轮廓
        drawContours(dstImage, src_contours, i, color,2,8,src_hierarchy,0,cv::Point());
        //绘制圆
        //circle(dstImage, src_mc[i], 4, color,-1,8,0);
        
    }
    cv::Mat dstImage1=cv::Mat::zeros(out_grayImage2.size(), CV_8UC3);
    for(unsigned int i=0;i<tmp_contours.size();++i)
    {
        //随机生成颜色值
        cv::Scalar color=cv::Scalar(0,0,255);
        //绘制外层和内层轮廓
        drawContours(dstImage1, tmp_contours, i, color,1,8,std::vector<cv::Vec4i>(),0,cv::Point());
    }
    
    //找到匹配位置
    cv::Mat LocImage;
    //5表示利用归一化相关系数匹配法
    cv::matchTemplate(dstImage, dstImage1, LocImage, matchMethod);
    cv::normalize(LocImage, LocImage,0,1,cv::NORM_MINMAX,-1,cv::Mat());
    cv::Point maxLocation;
    cv::minMaxLoc(LocImage,0,0,0,&maxLocation,cv::Mat());
    
    for(unsigned int i=0;i<match_contours.size();++i)
    {
        //绘制外层和内层轮廓
        drawContours(Image1, match_contours, i, cv::Scalar(0,0,255),2,8,std::vector<cv::Vec4i>(),0,cv::Point(maxLocation.x,maxLocation.y));
    }
    Image1.copyTo(Image3);

}
